-module(core).
-export([start/0]).

%==========================================
%TODO:
%==========================================
%Заменить io:format() на вывод в log-файл
%Отладить ошибки:
%    1.TCP/UDP сокеты не возвращают сообщения клиента


start() ->
    TcpPort = 1337,
    UdpPort = 1488,
    TcpOptions = [{active, false}, {reuseaddr, true}],
    UdpOptions = [{active, false}, {reuseaddr, true}],
    {ok, TcpSocket} = gen_tcp:listen(TcpPort, TcpOptions),
    {ok, UdpSocket} = gen_udp:open(UdpPort, UdpOptions),
    io:format("TCP server started and listening on port ~w~n", [TcpPort]),
    io:format("UDP server started and listening on port ~w~n", [UdpPort]),
    spawn(fun() -> accept_tcp_connections(TcpSocket) end),
    io:format("TCP-process had spawn ~n"),
    spawn(fun() -> receive_udp_data(UdpSocket) end),
    io:format("UDP-process had spawn ~n").

accept_tcp_connections(Listen) ->
    case gen_tcp:accept(Listen) of
        {ok, Socket} ->
	    io:format(Socket:peername()),
            io:format("TCP connection accepted from ~w~n", [inet:ntoa(Socket:peername())]), % что такое inet:ntoa? что такое Socket:peername? Почему сокет даёт краш-репорт?
            spawn(fun() -> handle_tcp_connection(Socket) end),
            accept_tcp_connections(Listen);
        {error, closed} ->
            ok;
        {error, Reason} ->
            io:format("Error accepting TCP connection: ~w~n", [Reason]),
            accept_tcp_connections(Listen)
    end.

handle_tcp_connection(Socket) ->
    case gen_tcp:recv(Socket, 0) of
        {ok, Data} ->
            io:format("Received TCP data: ~w~n", [Data]),
            gen_tcp:send(Socket, Data),
            handle_tcp_connection(Socket);
        {error, closed} ->
            gen_tcp:close(Socket);
        {error, Reason} ->
            io:format("Error receiving TCP data: ~w~n", [Reason]),
            gen_tcp:close(Socket)
    end.

receive_udp_data(Socket) ->
    case gen_udp:recv(Socket, 0) of % Что ему не нравится тут?
        {ok, Data, Addr, Port} ->
            io:format("Received UDP data: ~w~n", [Data]),
            gen_udp:send(Socket, Addr, Port, Data),
            receive_udp_data(Socket);
        {error, closed} ->
            ok;
        {error, Reason} ->
            io:format("Error receiving UDP data: ~w~n", [Reason]),
            receive_udp_data(Socket)
    end.
